﻿using System;
using System.Collections.Generic;
using System.Text;
using DailyDiet.Models;
using DailyDiet.Services.Constant;

namespace DailyDiet.Services.Impl
{
    /// <summary>
    /// 这是推荐指数类 ViewModel不可直接调用
    /// </summary>
    public class RecommendServiceImpl: IRecommendService
    {
        private ItemWeight _itemWeight = new ItemWeight();

        private DietStander _dietStander = new DietStander();

        private IPreferenceStorage _preferenceStorage;

        private UserTastePreference _userTastePreference;

        private double _spicyIndex;


        private double _sweetIndex;

        private double _healthIndex;
        private double _tasteIndex;

        /// <summary>
        /// 获取一个菜品组合的推荐指数
        /// </summary>
        /// <param name="diets">菜品集合</param>
        /// <returns></returns>
        public double GetRecommendIndex(List<Diet> diets) {
            Diet totalDiet = new Diet();
            var properties = new string[] {
                "Protein", "Fat", "Sugars", "Cellulose", "Vitamin",
                "Carbohydrate", "SweetIndex", "SpicyIndex"
            };
            foreach (var diet in diets) {
                foreach (var property in properties) {
                    totalDiet.GetType().GetProperty(property).SetValue(
                        totalDiet, 
                        (double)totalDiet.GetType().GetProperty(property).GetValue(totalDiet, null) 
                            + (double)diet.GetType().GetProperty(property).GetValue(diet,null));
                }
            }

            totalDiet.SpicyIndex /= diets.Count;
            totalDiet.SweetIndex /= diets.Count;

            double h1 = 0;
            double h21 = 0;
            double h22 = 0;

            double t1 = 0;
            double t21 = 0;
            double t22 = 0;
            var propertiesHealth = new string[] { "Protein", "Fat", "Sugars", "Cellulose", "Vitamin", "Carbohydrate" };
            var propertiesTaste = new string[] {"SweetIndex", "SpicyIndex"};
            
            foreach (var property in propertiesHealth) {
                double Di = (double) totalDiet.GetType().GetProperty(property).GetValue(totalDiet, null);
                double Wi = (double) _itemWeight.GetType().GetProperty(property).GetValue(_itemWeight, null);
                double Si = (double) _dietStander.GetType().GetProperty(property).GetValue(_dietStander, null);

                h1 += Di * Wi * Si;
                h21 += Di * Wi * Di;
                h22 += Si * Wi * Si;
            }

            foreach (var property in propertiesTaste)
            {
                double Di = (double)totalDiet.GetType().GetProperty(property).GetValue(totalDiet, null);
                double Si = (double)_userTastePreference.GetType().GetProperty(property).GetValue(_userTastePreference, null);

                t1 += Di * Si;
                t21 += Di * Di;
                t22 += Si * Si;
            }

            var sore = _healthIndex * (h1 / Math.Sqrt(h21 * h22)) +
                             _tasteIndex * (t1 / Math.Sqrt(t21 * t22));

            return sore;
        }

        public RecommendServiceImpl(IPreferenceStorage preferenceStorage) {
            _preferenceStorage = preferenceStorage;
            _spicyIndex = _preferenceStorage.Get(TasteSetConstant.SpicyIndexKey,
                TasteSetConstant.DefaultIndex);
            _sweetIndex = _preferenceStorage.Get(TasteSetConstant.SweetIndexKey,
                TasteSetConstant.DefaultIndex);
            _tasteIndex = _preferenceStorage.Get(TasteSetConstant.TasteIndexKey,
                TasteSetConstant.DefaultIndex);
            _healthIndex = _preferenceStorage.Get(
                TasteSetConstant.HealthIndexKey, TasteSetConstant.DefaultIndex);
            _userTastePreference = new UserTastePreference() {
                SpicyIndex = _spicyIndex, SweetIndex = _sweetIndex
            };
        }
    }

    public class UserTastePreference {
        public double SweetIndex { set; get; }
        public double SpicyIndex { set; get; }
    }

    /// <summary>
    /// 权重类，每个营养指标的权重
    /// </summary>
    public class ItemWeight {
        public double Protein {
            get => 8;
        }

        public double Fat {
            get => 6;
        }

        public double Sugars
        {
            get => 7;
        }

        public double Cellulose {
            get => 4;
        }
        public double Vitamin {
            get => 6;
        }
        public double Carbohydrate { 
            get => 7;
        }
    }
    /// <summary>
    /// 
    /// </summary>
    public class DietStander {
        public double Protein {
            get => 40;
        }
        public double Fat
        {
            get => 26;
        }
        public double Sugars
        {
            get => 30;
        }
        public double Cellulose
        {
            get => 14;
        }
        public double Vitamin
        {
            get => 33;
        }
        public double Carbohydrate
        {
            get => 96;
        }
    }
}
